publicfinalclassMessageimplementsParcelable { /** * User-defined message code so that the recipient can identify * what this message is about. Each {@link Handler} has its own name-space * for message codes, so you do not need to worry about yours conflicting * with other handlers. */ publicint what;
/** * arg1 and arg2 are lower-cost alternatives to using * {@link #setData(Bundle) setData()} if you only need to store a * few integer values. */ publicint arg1;
/** * arg1 and arg2 are lower-cost alternatives to using * {@link #setData(Bundle) setData()} if you only need to store a * few integer values. */ publicint arg2;
/** * An arbitrary object to send to the recipient. When using * {@link Messenger} to send the message across processes this can only * be non-null if it contains a Parcelable of a framework class (not one * implemented by the application). For other data transfer use * {@link #setData}. * * <p>Note that Parcelable objects here are not supported prior to * the {@link android.os.Build.VERSION_CODES#FROYO} release. */ public Object obj; @UnsupportedAppUsage /*package*/int flags;
/** * The targeted delivery time of this message. The time-base is * {@link SystemClock#uptimeMillis}. * @hide Only for use within the tests. */ @UnsupportedAppUsage @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) publiclong when;
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ publicstatic Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Messagem= sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } returnnewMessage(); }
/** * Same as {@link #obtain()}, but copies the values of an existing * message (including its target) into the new one. * @param orig Original message to copy. * @return A Message object from the global pool. */ publicstatic Message obtain(Message orig) { Messagem= obtain(); m.what = orig.what; m.arg1 = orig.arg1; m.arg2 = orig.arg2; m.obj = orig.obj; m.replyTo = orig.replyTo; m.sendingUid = orig.sendingUid; m.workSourceUid = orig.workSourceUid; if (orig.data != null) { m.data = newBundle(orig.data); } m.target = orig.target; m.callback = orig.callback;
return m; }
/** * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned. * @param h Handler to assign to the returned Message object's <em>target</em> member. * @return A Message object from the global pool. */ publicstatic Message obtain(Handler h) { Messagem= obtain(); m.target = h;
return m; }
/** * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on * the Message that is returned. * @param h Handler to assign to the returned Message object's <em>target</em> member. * @param callback Runnable that will execute when the message is handled. * @return A Message object from the global pool. */ publicstatic Message obtain(Handler h, Runnable callback) { Messagem= obtain(); m.target = h; m.callback = callback;
return m; }
/** * Same as {@link #obtain()}, but sets the values for both <em>target</em> and * <em>what</em> members on the Message. * @param h Value to assign to the <em>target</em> member. * @param what Value to assign to the <em>what</em> member. * @return A Message object from the global pool. */ publicstatic Message obtain(Handler h, int what) { Messagem= obtain(); m.target = h; m.what = what;
return m; }
/** * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em> * members. * @param h The <em>target</em> value to set. * @param what The <em>what</em> value to set. * @param obj The <em>object</em> method to set. * @return A Message object from the global pool. */ publicstatic Message obtain(Handler h, int what, Object obj) { Messagem= obtain(); m.target = h; m.what = what; m.obj = obj;
return m; }
/** * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, * <em>arg1</em>, and <em>arg2</em> members. * * @param h The <em>target</em> value to set. * @param what The <em>what</em> value to set. * @param arg1 The <em>arg1</em> value to set. * @param arg2 The <em>arg2</em> value to set. * @return A Message object from the global pool. */ publicstatic Message obtain(Handler h, int what, int arg1, int arg2) { Messagem= obtain(); m.target = h; m.what = what; m.arg1 = arg1; m.arg2 = arg2;
return m; }
/** * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members. * * @param h The <em>target</em> value to set. * @param what The <em>what</em> value to set. * @param arg1 The <em>arg1</em> value to set. * @param arg2 The <em>arg2</em> value to set. * @param obj The <em>obj</em> value to set. * @return A Message object from the global pool. */ publicstatic Message obtain(Handler h, int what, int arg1, int arg2, Object obj) { Messagem= obtain(); m.target = h; m.what = what; m.arg1 = arg1; m.arg2 = arg2; m.obj = obj;
/** * Return a Message instance to the global pool. * <p> * You MUST NOT touch the Message after calling this function because it has * effectively been freed. It is an error to recycle a message that is currently * enqueued or that is in the process of being delivered to a Handler. * </p> */ publicvoidrecycle() { if (isInUse()) { if (gCheckRecycle) { thrownewIllegalStateException("This message cannot be recycled because it " + "is still in use."); } return; } recycleUnchecked(); } /** * Return the targeted delivery time of this message, in milliseconds. */ publiclonggetWhen() { return when; }
/** * Retrieve the {@link android.os.Handler Handler} implementation that * will receive this message. The object must implement * {@link android.os.Handler#handleMessage(android.os.Message) * Handler.handleMessage()}. Each Handler has its own name-space for * message codes, so you do not need to * worry about yours conflicting with other handlers. */ public Handler getTarget() { return target; }
/** * Retrieve callback object that will execute when this message is handled. * This object must implement Runnable. This is called by * the <em>target</em> {@link Handler} that is receiving this Message to * dispatch it. If * not set, the message will be dispatched to the receiving Handler's * {@link Handler#handleMessage(Message)}. */ public Runnable getCallback() { return callback; }
/** * Obtains a Bundle of arbitrary data associated with this * event, lazily creating it if necessary. Set this value by calling * {@link #setData(Bundle)}. Note that when transferring data across * processes via {@link Messenger}, you will need to set your ClassLoader * on the Bundle via {@link Bundle#setClassLoader(ClassLoader) * Bundle.setClassLoader()} so that it can instantiate your objects when * you retrieve them. * @see #peekData() * @see #setData(Bundle) */ public Bundle getData() { if (data == null) { data = newBundle(); }
return data; }
/** * Like getData(), but does not lazily create the Bundle. A null * is returned if the Bundle does not already exist. See * {@link #getData} for further information on this. * @see #getData() * @see #setData(Bundle) */ public Bundle peekData() { return data; }
/** * Sets a Bundle of arbitrary data values. Use arg1 and arg2 members * as a lower cost way to send a few simple integer values, if you can. * @see #getData() * @see #peekData() */ publicvoidsetData(Bundle data) { this.data = data; }
/** * Sends this Message to the Handler specified by {@link #getTarget}. * Throws a null pointer exception if this field has not been set. */ publicvoidsendToTarget() { target.sendMessage(this); }
/** * Returns true if the message is asynchronous, meaning that it is not * subject to {@link Looper} synchronization barriers. * * @return True if the message is asynchronous. * * @see #setAsynchronous(boolean) */ publicbooleanisAsynchronous() { return (flags & FLAG_ASYNCHRONOUS) != 0; }
/** * Sets whether the message is asynchronous, meaning that it is not * subject to {@link Looper} synchronization barriers. * <p> * Certain operations, such as view invalidation, may introduce synchronization * barriers into the {@link Looper}'s message queue to prevent subsequent messages * from being delivered until some condition is met. In the case of view invalidation, * messages which are posted after a call to {@link android.view.View#invalidate} * are suspended by means of a synchronization barrier until the next frame is * ready to be drawn. The synchronization barrier ensures that the invalidation * request is completely handled before resuming. * </p><p> * Asynchronous messages are exempt from synchronization barriers. They typically * represent interrupts, input events, and other signals that must be handled independently * even while other work has been suspended. * </p><p> * Note that asynchronous messages may be delivered out of order with respect to * synchronous messages although they are always delivered in order among themselves. * If the relative order of these messages matters then they probably should not be * asynchronous in the first place. Use with caution. * </p> * * @param async True if the message is asynchronous. * * @see #isAsynchronous() */ publicvoidsetAsynchronous(boolean async) { if (async) { flags |= FLAG_ASYNCHRONOUS; } else { flags &= ~FLAG_ASYNCHRONOUS; } }
/** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}). */ publicMessage() { } }
Looper每次循环在做什么
取消息
分发消息
1 2 3 4 5 6 7 8 9 10 11 12
@SuppressWarnings({"UnusedTokenOfOriginalCallingIdentity", "ClearIdentityCallNotFollowedByTryFinally"}) privatestaticbooleanloopOnce(final Looper me, finallong ident, finalint thresholdOverride) { Messagemsg= me.mQueue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. returnfalse; } msg.target.dispatchMessage(msg); // 省略部分大概是和observer交互还有打log }
Handler.dispatchMessage
有callback就执行callback
没有则通过mCallback对象或者子类重写handleMessage分发消息。
1 2 3 4 5 6 7 8 9 10 11 12
publicvoiddispatchMessage(@NonNull Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
booleanenqueueMessage(Message msg, long when) { if (msg.target == null) { thrownewIllegalArgumentException("Message must have a target."); }
synchronized (this) { if (msg.isInUse()) { thrownewIllegalStateException(msg + " This message is already in use."); }
msg.markInUse(); msg.when = when; Messagep= mMessages; boolean needWake; if (p == null || when == 0 || when < p.when) { // New head, wake up the event queue if blocked. msg.next = p; mMessages = msg; needWake = mBlocked; } else { // Inserted within the middle of the queue. Usually we don't have to wake // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { needWake = false; } } msg.next = p; // invariant: p == prev.next prev.next = msg; }
// We can assume mPtr != 0 because mQuitting is false. if (needWake) { nativeWake(mPtr); } } returntrue; }
@UnsupportedAppUsage Message next() { intpendingIdleHandlerCount= -1; // -1 only during first iteration intnextPollTimeoutMillis=0; for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); }
synchronized (this) { // 只有一个线程能拿消息 // Try to retrieve the next message. Return if found. finallongnow= SystemClock.uptimeMillis(); MessageprevMsg=null; Messagemsg= mMessages; if (msg != null && msg.target == null) { // Stalled by a barrier. Find the next asynchronous message in the queue. do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null) { if (now < msg.when) { // Next message is not ready. Set a timeout to wake up when it is ready. nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); // nextPollTimeoutMillis的计算 } else { // Got a message. mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; if (DEBUG) Log.v(TAG, "Returning message: " + msg); msg.markInUse(); return msg; // 拿到消息,返回 } } else { // No more messages. nextPollTimeoutMillis = -1; } } } }
if (r.app.executingServices.size() == 0) { if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, "No more executingServices of " + r.shortName); mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
除了主体逻辑,发生ANR时还会输出各种类别的日志:
event log:通过检索”am_anr”关键字,可以找到发生ANR的应用
main log:通过检索”ANR in “关键字,可以找到ANR的信息,日志的上下文会包含CPU的使用情况
dropbox:通过检索”anr”类型,可以找到ANR的信息
traces:发生ANR时,各进程的函数调用栈信息